// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build haxe

package atomic

import "github.com/tardisgo/tardisgo/haxe/hx"

// A Value provides an atomic load and store of a consistently typed value.
// Values can be created as part of other data structures.
// The zero value for a Value returns nil from Load.
// Once Store has been called, a Value must not be copied.
type Value struct {
	v interface{}
}

// ifaceWords is interface{} internal representation.
//type ifaceWords struct {
//	typ  unsafe.Pointer
//	data unsafe.Pointer
//}

// Load returns the value set by the most recent Store.
// It returns nil if there has been no call to Store for this Value.
func (v *Value) Load() (x interface{}) {
	/*
		vp := (*ifaceWords)(unsafe.Pointer(v))
		typ := LoadPointer(&vp.typ)
		if typ == nil || uintptr(typ) == ^uintptr(0) {
			// First store not yet completed.
			return nil
		}
		data := LoadPointer(&vp.data)
		xp := (*ifaceWords)(unsafe.Pointer(&x))
		xp.typ = typ
		xp.data = data
		return
	*/
	return v.v
}

// Store sets the value of the Value to x.
// All calls to Store for a given Value must use values of the same concrete type.
// Store of an inconsistent type panics, as does Store(nil).
func (v *Value) Store(x interface{}) {
	if x == nil {
		panic("sync/atomic: store of nil value into Value")
	}
	if v.v != nil && hx.CodeBool("", "_a.itemAddr(0).load().typ!=_a.itemAddr(1).load().typ;", v.v, x) {
		panic("sync/atomic: store of inconsistently typed value into Value")
	}
	v.v = x

	/*
		vp := (*ifaceWords)(unsafe.Pointer(v))
		xp := (*ifaceWords)(unsafe.Pointer(&x))
		for {
			typ := LoadPointer(&vp.typ)
			if typ == nil {
				// Attempt to start first store.
				// Disable preemption so that other goroutines can use
				// active spin wait to wait for completion; and so that
				// GC does not see the fake type accidentally.
				runtime_procPin()
				if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
					runtime_procUnpin()
					continue
				}
				// Complete first store.
				StorePointer(&vp.data, xp.data)
				StorePointer(&vp.typ, xp.typ)
				runtime_procUnpin()
				return
			}
			if uintptr(typ) == ^uintptr(0) {
				// First store in progress. Wait.
				// Since we disable preemption around the first store,
				// we can wait with active spinning.
				continue
			}
			// First store completed. Check type and overwrite data.
			if typ != xp.typ {
				panic("sync/atomic: store of inconsistently typed value into Value")
			}
			StorePointer(&vp.data, xp.data)
			return
		}
	*/
}

// Disable/enable preemption, implemented in runtime.
//func runtime_procPin()
//func runtime_procUnpin()
